// 网站学院-Threejs 3D虚拟客服项目-3D数字人渲染性能
//优化任务工单 2.13
/*预加载：在页面加载过程中，通过异步加载和懒加载技术，预加
载关键的 3D 资源（如模型、纹理、动画等），减少页面初次加载时
的卡顿。*/ 
import React, { useRef, useState, useEffect, Suspense } from'react';
import { Canvas, primitive } from '@react-three/fiber';
import { OrbitControls, useGLTF } from '@react-three/drei';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import * as THREE from 'three';


// 定义 3D 模型资源数组
const modelUrls = ['/models/zuizhong.glb'];

// 预加载函数
const preloadModels = () => {
    return Promise.all(modelUrls.map(url => new Promise((resolve, reject) => {
        const loader = new GLTFLoader();
        loader.load(url, resolve, undefined, reject);
    })));
};

// 定义 3D 模型组件
const ModelViewer: React.FC<{ modelUrl: string }> = ({ modelUrl }) => {
    const modelRef = useRef<THREE.Group>(null);
    const [mixer, setMixer] = useState<THREE.AnimationMixer | null>(null);
    const { scene, animations } = useGLTF(modelUrl); // 加载 GLTF 文件

    // 初始化动画混合器
    useEffect(() => {
        if (animations.length > 0 && modelRef.current) {
            const newMixer = new THREE.AnimationMixer(modelRef.current);
            animations.forEach((clip) => {
                newMixer.clipAction(clip).play(); // 播放每个动画
            });
            setMixer(newMixer);
        }
    }, [animations]);

    // 更新动画
    useEffect(() => {
        const animate = () => {
            if (mixer) {
                mixer.update(0.006); // 每帧更新动画
            }
            requestAnimationFrame(animate); // 递归调用以更新动画
        };
        animate();
    }, [mixer]);

    return (
        <primitive ref={modelRef} object={scene} scale={2.8} position={[0.8, -2.5, -0.5]} />
    );
};

// 主组件
const App = () => {
    const [isLoaded, setIsLoaded] = useState(false);
    const [LoadingError,setLoadingError] = useState<string | null>(null);
    useEffect(() => {
        const loadResources=async()=>{
            try{
                await preloadModels();
                setIsLoaded(true);
            }catch(error){
                console.error('Failed to load 3D models:', error);
                setLoadingError('Failed to load 3D models. Please try again later.')
            }
        }
       loadResources();
    }, []);
    return (
        <div style={{ height: '100%', width: '100%' }}>
            <Suspense fallback={<div>Loading 3D models...</div>}>
               {LoadingError?(
                <div style={{color:'red'}}>{LoadingError}</div>
               ):isLoaded?(
                 <Canvas style={{width:'100%',height:'100%'}}>
                   <ambientLight intensity={1} />
                   <ModelViewer modelUrl='/models/zuizhong.glb'></ModelViewer>
                   <OrbitControls />
                 </Canvas>
               ):null}
            </Suspense>
        </div>
    );
};

export default App;